; $Id$
;
;+
; NAME:
;   MEDIANANYSIZE
;
; PURPOSE:
;   This procedure allows the user to select files to be added
;   to a list to then be combined (BOTH added AND medianed) after optimizing the alignment.
;   Images of any size can be combined.
;
; CALLING SEQUENCE:
;   median_anysize
;
; OPTIONAL INPUTS:
;    NONE
;
; MODIFICATION HISTORY:
;    Written by:   SBeland CU-Boulder/CASA, September 2004
;    Modified by FHearty CU-Boulder/CASA, April 2005
;-

;----------------------------------------------------------------------------
PRO STACKNCOMB_EVENT, sEvent

    WIDGET_CONTROL, sEvent.id, GET_UVALUE=uval

    ; Handle KILL requests.
    IF TAG_NAMES(sEvent, /STRUCTURE_NAME) EQ 'WIDGET_KILL_REQUEST' THEN BEGIN
       ; Destroy the objects.
       WIDGET_CONTROL, sEvent.top, /DESTROY
       RETURN
    ENDIF

    ; Get the state structure stored in the user value of the window
    WIDGET_CONTROL, GET_UVALUE=state, sEvent.top, /NO_COPY

    ; Handle other events.
    CASE uval OF
        'SELECTREF' : BEGIN
            ; bring up the file browser and get the reference file
            reffile = DIALOG_PICKFILE(GROUP=state.wBase, /MUST_EXIST, $
                       PATH=state.initPath, GET_PATH=newpath, FILTER="*.fits")
            IF newpath NE state.initPath AND newpath NE '' THEN state.initPath = newpath

            ; If the user didn't cancel the standard file dialog
            IF STRLEN(reffile[0]) GT 0 THEN BEGIN
               state.reffile = reffile[0]
               ; update the text widget
               WIDGET_CONTROL, state.wRefFile, SET_VALUE=state.reffile

            ; if the outfile (for added images) is empty create a default one
               if state.outfile eq '' then begin
                   fdecomp,reffile,disk,dir,fname,ext
                   state.outfile = dir+fname+'_sna.'+ext
                   WIDGET_CONTROL, state.wOutFile, SET_VALUE=state.outfile
               endif

            ; if the medfile (for median'd images)is empty create a default one
               if state.medfile eq '' then begin
                   fdecomp,reffile,disk,dir,fname,ext
                   state.medfile = dir+fname+'_snm.'+ext
                   WIDGET_CONTROL, state.wMedFile, SET_VALUE=state.medfile
               endif
            ENDIF
        END

        'SELECTOUT' : BEGIN
            ; bring up the file browser and get the output file
            outfile = DIALOG_PICKFILE(GROUP=state.wBase, /MUST_EXIST, $
                       PATH=state.initPath, GET_PATH=newpath, FILTER="*.fits")

            ; use the same file for median output image
            outmedfile=outfile

            IF newpath NE state.initPath AND newpath NE '' THEN state.initPath = newpath

            ; If the user didn't cancel the standard file dialog
            IF STRLEN(outfile[0]) GT 0 THEN BEGIN
            state.outfile = outfile[0]

            ; use same name again
            state.outmedfile = outmedfile[0]

               ; update the text widgets
               WIDGET_CONTROL, state.wOutFile, SET_VALUE=state.outfile
               WIDGET_CONTROL, state.wOutMedFile, SET_VALUE=state.outmedfile
            ENDIF
        END

        'SELECT' : BEGIN
            ; bring up the file browser and add to list
            fileName = DIALOG_PICKFILE(GROUP=state.wBase, /MULTIPLE_FILES, /MUST_EXIST, $
                       PATH=state.initPath, GET_PATH=newpath, FILTER="*.fits")
            IF newpath NE state.initPath AND newpath NE '' THEN state.initPath = newpath

            ; If the user didn't cancel the standard file dialog
            IF STRLEN(fileName[0]) GT 0 THEN BEGIN

               ; first make sure that it is not already in the list
               IF (*state.listarr)[0] EQ "" THEN BEGIN
                  ; list is empty
                  PTR_FREE, state.listarr
                  state.nlist = N_ELEMENTS(fileName)
                  state.listarr = PTR_NEW(fileName, /NO_COPY)
               ENDIF ELSE BEGIN
                  FOR i=0, N_ELEMENTS(fileName)-1 DO BEGIN
                     pos = WHERE(fileName[i] EQ (*state.listarr)[0:state.nlist-1])
                     IF pos[0] EQ -1 THEN BEGIN
                        *state.listarr = [*state.listarr, fileName[i]]
                        state.nlist = state.nlist + 1
                     ENDIF
                  ENDFOR
               ENDELSE
               WIDGET_CONTROL, state.wList, SET_VALUE=(*state.listarr)
               WIDGET_CONTROL, state.wProcessButton, SENSITIVE=1
               WIDGET_CONTROL, state.wClearButton, SENSITIVE=1
               WIDGET_CONTROL, state.wListLabel, $
                  SET_VALUE='Files to Process:  '+STRTRIM(STRING(state.nlist),2)
            ENDIF
        END

        'REMOVE' : BEGIN
            ; remove selected files from the list
            pos = WIDGET_INFO(state.wList, /LIST_SELECT)
            IF pos[0] NE -1 THEN BEGIN
               (*state.listarr)[pos] = ""
               state.nlist = state.nlist - N_ELEMENTS(pos)
               IF state.nlist EQ 0 THEN BEGIN
                  pos=0
                  PTR_FREE, state.listarr
                  state.listarr = PTR_NEW("")
                  WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=0
                  WIDGET_CONTROL, state.wClearButton, SENSITIVE=0
                  WIDGET_CONTROL, state.wProcessButton, SENSITIVE=0
               ENDIF ELSE BEGIN
                  newlist = (*state.listarr)[WHERE(*state.listarr ne "")]
                  PTR_FREE, state.listarr
                  state.listarr = PTR_NEW(newlist, /NO_COPY)
               ENDELSE
               WIDGET_CONTROL, state.wList, SET_VALUE=(*state.listarr)
               WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=0
               WIDGET_CONTROL, state.wListLabel, $
                  SET_VALUE='Files to Process:  '+STRTRIM(STRING(state.nlist),2)
            ENDIF

          END

        'CLEAR' : BEGIN
            ; clear all the files in the list
            PTR_FREE, state.listarr
            state.listarr = PTR_NEW("")
            state.nlist = 0
            WIDGET_CONTROL, state.wList, SET_VALUE=['']
            WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=0
            WIDGET_CONTROL, state.wClearButton, SENSITIVE=0
            WIDGET_CONTROL, state.wProcessButton, SENSITIVE=0
            WIDGET_CONTROL, state.wListLabel, $
               SET_VALUE='Files to Process:  '+STRTRIM(STRING(state.nlist),2)
          END

        'PROCESS' : BEGIN
             ; disable the buttons while processing
             WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=0
             WIDGET_CONTROL, state.wClearButton, SENSITIVE=0
             WIDGET_CONTROL, state.wProcessButton, SENSITIVE=0
             WIDGET_CONTROL, state.wCancelButton, SENSITIVE=0
             WIDGET_CONTROL, state.wSelectButton, SENSITIVE=0

             ; verify that we have specified reference and output files
             WIDGET_CONTROL, state.wRefFile, GET_VALUE=reffile
             WIDGET_CONTROL, state.wOutFile, GET_VALUE=outfile
             WIDGET_CONTROL, state.wMedFile, GET_VALUE=medfile

             if reffile eq '' then begin
                result = dialog_message('Please specify a REFERENCE file name',/error)
             endif else if outfile eq '' then begin
                result = dialog_message('Please specify an OUTPUT file name',/error)
             endif else begin

       ; make the array for medianing
           ; first, define the dimensions
           realdim = 1016
           oversize =260    ;this size is 256 + 4 reference pix (132 might be enough)
           lgsize = realdim + 2*oversize
           nlayers = state.nlist
          ; then make the oversized array
           medarr = make_array(lgsize,lgsize,nlayers,/float,value=!values.f_nan)



            ; get the reference image
                 state.reffile=reffile[0]

                 state.outfile=outfile[0]

                 refim = mrdfits(state.reffile, 0, refhd, /unsigned)

         ; trim the reference pixels and change the center pix accordingly
                 ;refim = refim[4:1019,4:1019] * 0.0

                 ;cp1=sxpar(refhd,'CRPIX1')
                 ;cp2=sxpar(refhd,'CRPIX2')
                 ;sxaddpar,refhd,'CRPIX1',cp1-4,/SaveComment
                 ;sxaddpar,refhd,'CRPIX2',cp2-4,/SaveComment
                 ;sxaddpar,refhd,'NAXIS1',realdim
                 ;sxaddpar,refhd,'NAXIS2',realdim
                 ;outim = refim
                 ;outhd = refhd

                 ;tempim=refim

            ; fill array with aligned zeros like oldim
               ;medarr[oversize:oversize+realdim-1,oversize:oversize+realdim-1,*]$
               ;=rebin(outim,realdim,realdim,nlayers)

            ; initialize a progress meter
                 p_meter = progress_meter(Text='Combining selected files', color=255)

                 ; loop through every file and send to sdi2fits
                 i=0
                 n=state.nlist

                 WHILE state.nlist NE 0 DO BEGIN
                    ; check if cancel button was pressed
                    IF (*p_meter).cancelFlag THEN BEGIN
                       progress_destroy, p_meter
                       WIDGET_CONTROL, state.wCancelButton, SENSITIVE=1
                       WIDGET_CONTROL, state.wSelectButton, SENSITIVE=1
                       WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=1
                       WIDGET_CONTROL, state.wClearButton, SENSITIVE=1
                       IF WIDGET_INFO(sEvent.top, /VALID_ID) THEN $
                          WIDGET_CONTROL, SET_UVALUE = state, sEvent.top, /NO_COPY
                       RETURN
                    ENDIF

                    print,'('+strtrim(string(i+1),2)+'/'+strtrim(string(n),2)+') Processing '+$
                          (*state.listarr)[0]

                ; start processing the file
                    fdecomp,(*state.listarr)[0],disk,dir,fname,ext
                    oldim = mrdfits((*state.listarr)[0], 0, oldhd, /silent, /unsigned)

          ; trim the reference pixels and change the center pix accordingly
                   ; oldim=oldim[4:1019,4:1019]
                   ; cp1=sxpar(oldhd,'CRPIX1')
                   ; cp2=sxpar(oldhd,'CRPIX2')
                   ; sxaddpar,oldhd,'CRPIX1',cp1-4,/SaveComment
                    ;sxaddpar,oldhd,'CRPIX2',cp2-4,/SaveComment
                    ;sxaddpar,oldhd,'NAXIS1',realdim
                    ;sxaddpar,oldhd,'NAXIS2',realdim

                 ;hastrom, oldim, oldhd, newim, newhd, refhd, missing=0



             ;outim += newim
             outhd = oldhd


                ;fill the medianing array one level at a time
                oldmedim=oldim
           ; sum the stack up to the current oversized image
;help, medarr
         sumsofar=TOTAL(medarr,3)
;help,sumsofar
          medarr[*,*,i] = oldmedim


IF i ge 1 THEN BEGIN

            ;sumsofar=TOTAL((medarr[*,*,0:i-1]),3)
                midxpix=970
                midypix=860
                incr=50
                 ; correlate the images to optimize the alignment
                 ;correl_optimize,sumsofar[midpix-incr:midpix+incr,midpix-incr:midpix+incr],$
                 ;medarr[midpix-incr:midpix+incr,midpix-incr:midpix+incr,i],xoff,yoff,/print
                 corrmat_analyze,correl_images(sumsofar[midxpix-incr:midxpix+incr,midypix-incr:midypix+incr],$
                 medarr[midxpix-incr:midxpix+incr,midypix-incr:midypix+incr,i]),xoff,yoff;,/print
                 ;corrmat_analyze,correl_images(sumsofar,$
                 ;medarr[*,*,i]),xoff,yoff;,/print

print,xoff
print,yoff
;stop
                    ; change the center pixels to align images
                    ;cp4=sxpar(newhd,'CRPIX1')
                    ;cp5=sxpar(newhd,'CRPIX2')
                    ;sxaddpar,newhd,'CRPIX1',cp4+xoff,/SaveComment
                    ;sxaddpar,newhd,'CRPIX2',cp5+yoff,/SaveComment

                ; shift array by the optimum numbers
                medarr[*,*,i]=shift(medarr[*,*,i],xoff,yoff)
help,medarr

ENDIF


                ; set the percentage done
                i=i+1
                progress_update, p_meter, FLOAT(i)*100.0 / FLOAT(n)

                ; remove the entry from the list
                (*state.listarr)[0] = ""
                state.nlist = state.nlist - 1


                    IF state.nlist EQ 0 THEN BEGIN
                       PTR_FREE, state.listarr
                       state.listarr = PTR_NEW('')
                       WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=0
                       WIDGET_CONTROL, state.wClearButton, SENSITIVE=0
                       WIDGET_CONTROL, state.wCancelButton, SENSITIVE=1
                       WIDGET_CONTROL, state.wSelectButton, SENSITIVE=1
                       WIDGET_CONTROL, state.wProcessButton, SENSITIVE=0
                       WIDGET_CONTROL, state.wList, SET_VALUE=['']
                    ENDIF ELSE BEGIN
                       newlist = (*state.listarr)[WHERE(*state.listarr NE "")]
                       PTR_FREE, state.listarr
                       state.listarr = PTR_NEW(newlist, /NO_COPY)
                       WIDGET_CONTROL, state.wList, SET_VALUE=(*state.listarr)
                    ENDELSE

                 ENDWHILE

                 ; write out the resulting stacked image
                 snahd=outhd
                 sxaddpar, snahd, 'HISTORY', 'Shifted and Added ';+fname+'.'+ext
                 print, 'Writing out '+outfile

                 ; add the aligned layers
           outim=total(medarr,3)
                 ; reverse the images left and right
                 outim = reverse (outim)
                 ; reverse the WCS
                 cd1=sxpar(snahd,'CD1_1')
                 sxaddpar,snahd,'CD1_1',cd1*(-1.0),/SaveComment
                 ; flip the center pixel
                 cp3=sxpar(snahd,'CRPIX1')
                 sxaddpar,snahd,'CRPIX1',realdim-cp3,/SaveComment
         ; Problem -- not sure why but comments lost on above two

                 mwrfits, outim, state.outfile, snahd, /create, /no_comment

                 ; median the stacked images
                 medim=median(medarr, dimension=3,/even)

                 ; write out the resulting medianed image
                 snmhd=outhd
                 sxaddpar, snmhd, 'HISTORY', 'Stacked and medianed ';+fname+'.'+ext
                  ; reverse the WCS
                 cd2=sxpar(snmhd,'CD1_1')
                 sxaddpar,snmhd,'CD1_1',cd1*(-1.0),/SaveComment
                 ;sxaddpar,snmhd,'CD1_1',(Double(-7.5681893863712E-05)),/SaveComment
                 ; flip the center pixel
                 cp4=sxpar(snmhd,'CRPIX1')
                 sxaddpar,snmhd,'CRPIX1',realdim-cp4,/SaveComment
         ; Problem -- not sure why but comments lost on above two

                 print, 'Writing out '+medfile



                 mwrfits, reverse(medim), state.medfile, snmhd, /create, /no_comment

                 ; get rid of meter
                 progress_destroy, p_meter

                 ; re-enable the buttons
                 IF WIDGET_INFO(state.wList, /LIST_SELECT) EQ -1 THEN BEGIN
                    WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=0
                    WIDGET_CONTROL, state.wClearButton, SENSITIVE=0
                 ENDIF ELSE BEGIN
                    WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=1
                    WIDGET_CONTROL, state.wClearButton, SENSITIVE=1
                 ENDELSE
                 WIDGET_CONTROL, state.wListLabel, $
                    SET_VALUE='Files to Process:  '+STRTRIM(STRING(state.nlist),2)

             endelse
          END

        'CANCEL' : BEGIN
            ; quit without changing the dB
            WIDGET_CONTROL, sEvent.top, /DESTROY
          END

        'LIST' : BEGIN
            ; a file was selected from the list
            pos = WIDGET_INFO(state.wList, /LIST_SELECT)
            IF pos[0] NE -1 THEN BEGIN
               WIDGET_CONTROL, state.wRemoveButton, SENSITIVE=1
            ENDIF
        END

        ELSE:
            ; ignore all other events
    ENDCASE

    ; Reset the windows user value to the updated state structure
    IF WIDGET_INFO(sEvent.top, /VALID_ID) THEN $
       WIDGET_CONTROL, SET_UVALUE = state, sEvent.top, /NO_COPY

END

;----------------------------------------------------------------------------
PRO median_anysize

    ; Create the widgets.
    xsize = 100

    title = 'STACKNCOMB  '
    wBase = WIDGET_BASE(COLUMN=2, TITLE=title, /TLB_KILL_REQUEST_EVENTS, TLB_FRAME_ATTR=1)

    wGuiBase      = WIDGET_BASE(wBase, ROW=4)
    wRefBase      = WIDGET_BASE(wGuiBase, COLUMN=2, FRAME=1)
    wRefLabel     = WIDGET_LABEL(wRefBase, VALUE='Reference File: ', /ALIGN_LEFT)
    wRefFile      = WIDGET_TEXT(wRefBase, VALUE='', /EDITABLE,  /NO_NEWLINE, XSIZE=52)
    wButtons      = WIDGET_BASE(wRefBase,/COLUMN, SPACE=30)
    wTopButtons   = WIDGET_BASE(wButtons,/COLUMN, SPACE=8)
    wSelectRef    = WIDGET_BUTTON(wTopButtons, XSIZE=xsize, VALUE='Select', UVALUE='SELECTREF')

    wOutBase      = WIDGET_BASE(wGuiBase, COLUMN=2, FRAME=1)
    wOutLabel     = WIDGET_LABEL(wOutBase, VALUE='Output Stacked File: ', /ALIGN_LEFT)
    wOutFile      = WIDGET_TEXT(wOutBase, VALUE='', /EDITABLE,  /NO_NEWLINE, XSIZE=52)
    wButtons      = WIDGET_BASE(wOutBase,/COLUMN, SPACE=30)
    wTopButtons   = WIDGET_BASE(wButtons,/COLUMN, SPACE=8)
    wSelectOut    = WIDGET_BUTTON(wTopButtons, XSIZE=xsize, VALUE='Select', UVALUE='SELECTOUT')

    wMedBase      = WIDGET_BASE(wGuiBase, COLUMN=2, FRAME=1)
    wMedLabel     = WIDGET_LABEL(wMedBase, VALUE='Output Medianed File: ', /ALIGN_LEFT)
    wMedFile      = WIDGET_TEXT(wMedBase, VALUE='', /EDITABLE,  /NO_NEWLINE, XSIZE=52)
    wButtons      = WIDGET_BASE(wMedBase,/COLUMN, SPACE=30)
    wTopButtons   = WIDGET_BASE(wButtons,/COLUMN, SPACE=8)
    wSelectOut    = WIDGET_BUTTON(wTopButtons, XSIZE=xsize, VALUE='Select', UVALUE='SELECTOUT')

    wListBase     = WIDGET_BASE(wGuiBase, COLUMN=2, FRAME=1)
    wListLabel    = WIDGET_LABEL(wListBase, VALUE='Files to COMBINE:  0', $
                    /ALIGN_LEFT, /DYNAMIC_RESIZE)
    wList         = WIDGET_LIST(wListBase, /MULTIPLE, XSIZE=59, YSIZE=20, UVALUE='LIST')

    wButtons      = WIDGET_BASE(wListBase,/COLUMN, SPACE=30)
    wTopButtons   = WIDGET_BASE(wButtons,/COLUMN, SPACE=8)
    wSelectButton = WIDGET_BUTTON(wTopButtons, XSIZE=xsize, VALUE='Select', UVALUE='SELECT')
    wRemoveButton = WIDGET_BUTTON(wTopButtons, XSIZE=xsize, VALUE='Remove', UVALUE='REMOVE')
    wClearButton  = WIDGET_BUTTON(wTopButtons, XSIZE=xsize, VALUE='Clear', UVALUE='CLEAR')

    wBottomButtons= WIDGET_BASE(wButtons,/COLUMN, /ALIGN_BOTTOM, SPACE=8)
    wProcessButton= WIDGET_BUTTON(wBottomButtons, XSIZE=xsize, VALUE='Process', UVALUE='PROCESS')
    wCancelButton = WIDGET_BUTTON(wBottomButtons, XSIZE=xsize, VALUE='Cancel', UVALUE='CANCEL')

   state = { $
             wBase: wBase, $
             wList: wList, $
             wListLabel: wListLabel, $
             wSelectRef: wSelectRef, $
             wRefFile: wRefFile, $
             wOutFile: wOutFile, $
             wMedFile: wMedFile, $
             wSelectButton: wSelectButton, $
             wRemoveButton: wRemoveButton, $
             wClearButton: wClearButton, $
             wProcessButton: wProcessButton, $
             wCancelButton: wCancelButton, $
             reffile: "", $
             outfile: "", $
             medfile: "", $
             listarr: PTR_NEW(""), $
             nlist: 0, $
             initPath: "./" $
           }

    ; set the initial browsing path to the default raw dir set by environment
    path = CEDAR_GETENV('CEDAR_FITS_ROOT')
    IF path NE '' THEN state.initPath=path

    ; Save the state structure in the window's user value
    WIDGET_CONTROL, wBase, SET_UVALUE=state

    WIDGET_CONTROL, wRemoveButton, SENSITIVE=0
    WIDGET_CONTROL, wClearButton, SENSITIVE=0
    WIDGET_CONTROL, wProcessButton, SENSITIVE=0

    WIDGET_CONTROL, wBase, /REALIZE

    XMANAGER, 'STACKNCOMB', wBase, /NO_BLOCK

END
